<!DOCTYPE html>

<html>
<head>
		<script>
			var lastMsg, allowed=false, dir=null, noThumbs=null;
			
			var locStor = {};
			
			function go() {
				console.log("deviceStorage");
				var free = false;
			
				window.addEventListener("message", onMessage,false);
				
				
				var idb = { req: window["indexedDB"].open("deviceStorage") };
				idb.req["onupgradeneeded"] = function(e) {
					//console.log("onupgradeneeded");
					var db = e.target.result;
					var os = db["createObjectStore"]("rsrc", { "keyPath": "k" });
				}
				idb.req["onsuccess"] = function(e) {
					var db = locStor.db = e.target.result;  //console.log(db);
					var os = db["transaction"](["rsrc"], "readwrite")["objectStore"]("rsrc");
					
					var req = os["get"]("fs0");
					req["onsuccess"] = function(e) {
						if(e.target.result) {
							if(localStorage.getItem("forget")=="1") {
								localStorage.removeItem("forget");
							}
							else {
								locStor.fset = e.target.result["fset"];
								//console.log(locStor.fset);
								dir = locStor.fset;
							}
							//allowed=true;   send("ready",true);  
						}
					};
				}
				
				allowed=false;  send("ready",false);  
				//allowed = free;
			}
			
			async function makeFolder(path) {
				path = __getPath(path);  //console.log(path);
				var fld = dir;  for(var i=0; i<path.length-1; i++) fld = await fld.getDirectoryHandle(path[i]);
				
				var dirHandle = await fld.getDirectoryHandle(path[path.length-1], { create: true });
				send("0","");
			}
			
			async function deleteFile(path) {
				path = __getPath(path);  //console.log(path);
				var fld = dir;  for(var i=0; i<path.length-1; i++) fld = await fld.getDirectoryHandle(path[i]);
				
				await fld.removeEntry(path[path.length-1], { recursive: true });
				send("0","");
			}
			
			async function saveFile (path, buff) {
				path = __getPath(path);  //console.log(path);
				var fld = dir;  for(var i=0; i<path.length-1; i++) fld = await fld.getDirectoryHandle(path[i]);
				
				var han = await fld.getFileHandle(path[path.length-1],{create:true});
				
				var wrt = await han.createWritable();//;.then(function(e) {e.write(buff); return e;}).then(function(e) {e.close()});
				await wrt.write(buff);
				await wrt.close();
				send("0","");
			}
			async function printFile(path) {
				path = __getPath(path);  //console.log(path);
				var fld = dir;  for(var i=0; i<path.length-1; i++) fld = await fld.getDirectoryHandle(path[i]);
				
				var han = await fld.getFileHandle(path[path.length-1]);
				var fil = await han.getFile();
				var buf = await fil.arrayBuffer();
				window.parent.postMessage(buf,"*");
			}
			
			var fmap,left,fls, gtime, timg;
			async function printFolder(path) {
				path = __getPath(path);  //console.log(path);
				var fld = dir;  for(var i=0; i<path.length; i++) fld = await fld.getDirectoryHandle(path[i]);
				
				fls = [];  fmap={};  left=0;  timg=0;  gtime=Date.now();
				var time = Date.now(), cnt=0, gotFile=false;
				for await (var entry of fld.values()) {
					var file = [entry.name,-1];  fls.push(file);
					
					//if(entry.kind=="file--") {  file[1]=100;  file.push(0);  }
					if(entry.kind=="file") {
						gotFile=true;
						fmap[entry.name]=fls.length-1;  left++;
						entry.getFile().then(fileLoaded);
						//var fil = await entry.getFile();  makeFile(fil, file);
					}
				}
				if(!gotFile) send("0",fls);
			}
			async function fileLoaded(fil) {
				file = fls[fmap[fil.name]];
				await makeFile(fil,file);  left--;
				if(left==0) {
					console.log(Date.now()-gtime, timg);
					send("0",fls);
				}
			}
			
			async function makeFile(fil, file) {
				var np = fil.name.split("."), ext = (np.length==1 ? "" : np.pop()).toLowerCase();
				file[1]=fil.size;
				file.push(~~(fil.lastModified/1000));  //return;
				if(ext=="jpeg") ext="jpg";
				if(ext=="tiff") ext="tif";
				if(["dng","cr2","nef","arw","3fr","fff","gpr"].indexOf(ext)!=-1) ext="tif";
				
				if(noThumbs) ext="---";
				var thmb=null;
				if(thmb==null && (ext=="jpg" || ext=="tif")) {  // || ext=="--psd"
					var lim = 130000;
					var buf = await fil.slice(0,(lim*1.5>fil.size) ? fil.size : lim).arrayBuffer();
					if(ext=="jpg" && buf.byteLength==fil.size) thmb = bufToUrl(buf, "jpg");
					else  thmb=findJPG(fil.name,buf);
				}
				//*
				if(thmb==null && (ext=="psd" || ext=="psb")) {
					var buf = await fil.slice(0,4096).arrayBuffer();
					buf = new Uint8Array(buf);  //console.log(buf);
					var off = 26;
					var clen = readUint(buf,off);  off+=4;  //console.log(clen);
					off+=clen;
					var rlen = readUint(buf,off);  off+=4;  //console.log(rlen);
					
					if(off+rlen<=4096) buf=buf.slice(off,off+rlen);
					else buf = new Uint8Array(await fil.slice(off,off+rlen).arrayBuffer());
						
					off = 0;
					while(off<buf.length) {
						var sign = readASCII(buf,off,4);  off+=4;  
						var resID = readUshort(buf,off);  off+=2;
						var sz = buf[off];  
						off+=sz+(1-(sz&1))+1;
						
						var asiz = readUint(buf,off);  off+=4;
						if(resID==1036) {
							//console.log(off, rlen);
							var tsz = readUint(buf,off+20);
							var io = off+28;  //console.log(buf.slice(io,io+tsz));
							thmb = bufToUrl(buf.slice(io,io+tsz).buffer,"jpg");
							break;
						}
						off+=asiz+(asiz&1);								
					}							
				}//*/
				if(thmb==null && fil.size<100000 && ["png","svg","bmp","gif","webp"].indexOf(ext)!=-1) {
					var buf = await fil.arrayBuffer();
					if(ext=="png") {
						var data=new Uint8Array(buf), off=16;
						var bf = new Uint8Array(4), dim=[];
						for(var i=0; i<2; i++) {
							for(var j=0; j<4; j++) bf[j] = data[off+3-j];
							dim.push((new Uint32Array(bf.buffer))[0]);
						}
						if(dim[0]*dim[1]<1e6) thmb=bufToUrl(buf,ext);
					}
					else thmb=bufToUrl(buf,ext);
				}
				if(thmb) {  file.push(thmb);  timg++;  }
			}
			
			function findJPG(name, buf) {
				buf = new Uint8Array(buf);  //console.log(buf);
				var d8=-1, d9=-1, end=buf.length-1;
				var ints = [];
				for(var i=2; i<end; i++) {
					if(buf[i]==255) {
						var b1=buf[i+1], b2=buf[i+2], b3 = buf[i+3];
						//if(b1==0xd8 && b2==0xff) console.log(name);
						if     (d8==-1 && b1==0xd8 && b2==0xff) d8=i;
						else if(d8!=-1 && b1==0xd9) {  d9=i;  ints.push(d8,d9);  d8=d9=-1;  }
					}
				}
				if(ints.length!=0) {
					d8=ints[0];  d9=ints[1];
					return bufToUrl(buf.slice(d8, d9+2).buffer, "jpg");
				}
			}
			
			var u8 = new Uint8Array(4);
			var u16 = new Uint16Array(u8.buffer);
			var u32 = new Uint32Array(u8.buffer);
			function readASCII (b, o, l) {  var out="";  for(var i=0; i<l; i++) out+=String.fromCharCode(b[o+i]);  return out;  }
			function readUshort(b, o) {  u8[0]=b[o+1];  u8[1]=b[o];  return u16[0];  }
			function readUint  (b, o) {  u8[0]=b[o+3];  u8[1]=b[o+2];  u8[2]=b[o+1];  u8[3]=b[o];  return u32[0];  }
			function bufToUrl(buf, ext) {
				var str=[];  buf=new Uint8Array(buf);
				for(var i=0; i<buf.length; i++) str.push(String.fromCharCode(buf[i]));
				return "data:image/"+ext+(ext=="svg"?"+xml":"")+";base64,"+btoa(str.join(""))
			}
			
			async function askPermissions() {
				if(dir)	{ 
					if(await dir.requestPermission({mode:"readwrite"})!="granted") {  send("1","You must give Photopea access to some folder.");  return;  }
				}
				else {
					try { dir = await window.showDirectoryPicker(); } 
					catch(e) {  send("1","You must give Photopea access to some folder.");  return;  }
					locStor.fset = dir;
				
					var os = locStor.db["transaction"](["rsrc"], "readwrite")["objectStore"]("rsrc");
					var ooo=os["put"]({  "k":"fs0", "fset":locStor.fset  });
					ooo.onerror = function(e) {  console.log(e);  alert("Storing failed. Browser says: "+e["target"]["error"]["message"],7000);  }
				}
				allowed = true;  printFolder("/");
			}
			
			function onMessage(e) {
				if((typeof e.data) == "string") {
					//console.log(e.data);
					
					if(window.showDirectoryPicker==null) {  send("1","Your browser can not perform this feature.");  return;  }
				
					var msg = null;
					try {  msg = JSON.parse(e.data);  }  catch(e) {  return;  }
					if(msg.code==null) return;
					
					if(!allowed) {  askPermissions();  return;  }
					
					
					if(msg.code=="show") {
						noThumbs=msg.nothumbs;
						printFolder(msg.prm);  
					}
					else if(msg.code=="load") {
						printFile(msg.prm);
					}
					else if(msg.code=="delete") {
						deleteFile(msg.prm);
					}
					else if(msg.code=="save" && msg.prm.endsWith("/")) makeFolder(msg.prm.slice(0,-1));  // making a folder
					else if(msg.code=="forget") {  console.log("forget message");  localStorage.setItem("forget", "1");  send("0","");  }
					else if(msg.code=="rename") {
						send("1","We can not rename files in your coputer yet.");
					}
					
					lastMsg=msg;
				}
				else {
					if(lastMsg.code=="save") saveFile(lastMsg.prm, e.data);
				}
			}
			
			function __getPath(path) {
				var pth = [];  if(path.length>1) pth=path.slice(1).split("/");
				return pth;
			}
			
			function send(code,prm) {
				var time = Date.now();
				var str = JSON.stringify({"code":code, "prm":prm});
				//console.log("json", Date.now()-time, str.length);
				window.parent.postMessage(str,"*");
			}
		</script>
	</head>
	<body onload="go()"></body>
</html>